﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using AccelerateSensor.Client.Controls;
using AccelerateSensor.Client.Tools;
using AccelerateSensor.Model.Node;
using AccelerateSensor.Service;
using ZbSkin.Frm;

namespace AccelerateSensor.Client.Forms
{
    public partial class FrmNodeRealtimeData : PopupForm
    {
        private readonly Panel _contentPanel;
        private readonly List<CommonChartControl> _chartControlList;
        private readonly string _gatewayUuid;
        private readonly string _nodeUuid;
        private readonly int _sleepTime;

        private readonly SynchronizationContext _context;

        private int _channelNumber;
        private string[] _channelNames;

        public FrmNodeRealtimeData(string gatewayUuid, string nodeUuid, int sleepTime)
        {
            InitializeComponent();

            _context = SynchronizationContext.Current;

            _gatewayUuid = gatewayUuid;
            _nodeUuid = nodeUuid;
            _sleepTime = sleepTime;

            _chartControlList = new List<CommonChartControl>();
            _contentPanel = new Panel();
            Controls.Add(_contentPanel);
        }

        private void FrmNodeRealtimeData_Load(object sender, EventArgs e)
        {
            FrmTitle = $@"实时数据图 - {_nodeUuid}";
            WindowState = FormWindowState.Maximized;

            if (string.IsNullOrWhiteSpace(_gatewayUuid) ||
                string.IsNullOrWhiteSpace(_nodeUuid))
            {
                return;
            }

            var gateway = AccelerateSensorService.Instance.GatewayInfoList
                .FirstOrDefault(t => _gatewayUuid.Equals(t.Uuid));
            var nodeData = gateway?.NodeList.FirstOrDefault(t => _nodeUuid.Equals(t.Uuid))?.Data;
            if (nodeData == null)
            {
                AccelerateSensorService.Instance.NodeDataChangedEvent += OnNodeDataChanged;
                return;
            }

            CreateCharts(nodeData);

            //下一帧刷新数据
            _context?.Post((state) =>
            {
                var data = (NodeData)state;
                UpdateNodeData(data);
                AccelerateSensorService.Instance.NodeDataChangedEvent += OnNodeDataChanged;
            }, nodeData);
        }

        private void FrmNodeRealtimeData_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (!string.IsNullOrWhiteSpace(_nodeUuid))
            {
                AccelerateSensorService.Instance.NodeDataChangedEvent -= OnNodeDataChanged;
            }
        }

        private void FrmNodeRealtimeData_SizeChanged(object sender, EventArgs e)
        {
            _contentPanel.Width = ClientSize.Width;
            _contentPanel.Height = ClientSize.Height - TitlePanel.Height;
            _contentPanel.Left = 0;
            _contentPanel.Top = TitlePanel.Bottom;

            ResizeChartControls();
        }

        private void CreateCharts(NodeData nodeData)
        {
            if (_chartControlList.Count > 0)
            {
                return;
            }

            _channelNumber = nodeData.ChanNum;
            _channelNames = nodeData.Names;
            if (_channelNumber <= 0 || _channelNames == null ||
                _channelNumber != _channelNames.Length)
            {
                return;
            }

            for (var i = 0; i < _channelNumber; i++)
            {
                var chartControl = new CommonChartControl(_channelNames[i], _sleepTime);
                _chartControlList.Add(chartControl);
                _contentPanel.Controls.Add(chartControl);
            }

            ResizeChartControls();
        }

        private void ResizeChartControls()
        {
            if (_chartControlList.Count == 0)
            {
                return;
            }

            var interval = 10;
            var width = _contentPanel.Width - interval * 2;
            var height = (_contentPanel.Height - (_channelNumber + 1) * interval) / _channelNumber;
            for (var i = 0; i < _channelNumber; i++)
            {
                var chartControl = _chartControlList[i];
                chartControl.Width = width;
                chartControl.Height = height;
                chartControl.Left = interval;
                chartControl.Top = (height + interval) * i;
            }
        }

        private void OnNodeDataChanged(NodeData nodeData)
        {
            if (_nodeUuid.Equals(nodeData?.NodeUuid))
            {
                _context?.Post((state) =>
                {
                    var data = (NodeData)state;
                    CreateCharts(data);
                    UpdateNodeData(data);
                }, nodeData);
            }
        }

        private void UpdateNodeData(NodeData nodeData)
        {
            try
            {
                for (var i = 0; i < _channelNumber; i++)
                {
                    var dataArray = nodeData.ValueList[i];
                    var chartControl = _chartControlList[i];
                    chartControl.AddData(dataArray, nodeData.UpdateTime);
                }
            }
            catch (Exception e)
            {
                LogHelper.AddErrorLog(e.Message);
            }
        }
    }
}
